package com.etcfg.etlaunch.ui;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;

import javax.swing.AbstractAction;
import javax.swing.ImageIcon;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.JToolBar;
import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableRowSorter;

import com.etcfg.etlaunch.ApplicationSetting;
import com.etcfg.etlaunch.ETLauncherApplication;
import com.etcfg.etlaunch.ETServer;
import com.etcfg.etlaunch.ServerStatus;

public class MainWindow implements PropertyChangeListener {
	private JFrame frame;
	private JTable serverList;
	private JSplitPane splitPane;
	private JPanel detailsPanel;

	private ServerListModel listModel;

	private ConnectToServerAction connectToServerAction;
	private AddServerAction addServerAction;
	private ChangePasswordAction changePasswordAction;
	private DeleteServerAction deleteServerAction;
	private CopyServerAction copyAction;
	private PasteServerAction pasteServerAction;
	private AboutAction aboutAction;

	private ETServer lastSelectedServer;
	private PlayersTableModel playerModel = new PlayersTableModel();
	private JTable playersTable = new JTable();
	private DisplaySettingAction settingsAction;
	private ETLauncherApplication application;

	public MainWindow(ETLauncherApplication data) {
		application = data;
		connectToServerAction = new ConnectToServerAction(this, data);
		addServerAction = new AddServerAction(this, data);
		changePasswordAction = new ChangePasswordAction(this, data);
		deleteServerAction = new DeleteServerAction(this, data);
		pasteServerAction = new PasteServerAction(this);
		copyAction = new CopyServerAction(this, data);
		aboutAction = new AboutAction(this);

		setListModel(new ServerListModel());
		connectToServerAction.setEnabled(false);
		setFrame(new JFrame());
		initializeServersTable();

		detailsPanel = new JPanel();

		splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
		JScrollPane serversScrollPane = new JScrollPane(getServerList());
		splitPane.add(serversScrollPane);

		splitPane.add(new JScrollPane(playersTable));
		playersTable.setModel(playerModel);
		playersTable.setAutoCreateRowSorter(true);
		playersTable.getColumnModel().getColumn(0).setCellRenderer(
				new PlayerNameCellRender());
		playersTable.setShowHorizontalLines(false);
		playersTable.setShowVerticalLines(false);
		playersTable.setIntercellSpacing(new Dimension(0, 0));
		playersTable.setAutoResizeMode(JTable.AUTO_RESIZE_NEXT_COLUMN);

		TableColumnModel columnModel = playersTable.getColumnModel();
		TableColumn column = columnModel.getColumn(2);
		column.setMaxWidth(40);
		column.setMinWidth(40);
		column.setPreferredWidth(40);
		column = columnModel.getColumn(1);
		column.setMaxWidth(80);
		column.setMinWidth(80);
		column.setPreferredWidth(80);

		JToolBar toolBar = new JToolBar();
		toolBar.add(addServerAction);
		toolBar.add(connectToServerAction);
		settingsAction = new DisplaySettingAction();
		settingsAction.setSettings(data.getApplicationSetting());
		settingsAction.setParent(frame);
		toolBar.add(settingsAction);
		toolBar.add(aboutAction);
		getFrame().setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
		getFrame().add(toolBar, BorderLayout.NORTH);
		getFrame().add(splitPane);

		getFrame().setTitle("Version " + ApplicationSetting.VERSION);
		getFrame().setIconImage(
				new ImageIcon(getClass().getResource(
						"/com/etcfg/etlaunch/ui/icons/etcfgIcon.gif"))
						.getImage());
		loadWindowSettings();
		getFrame().addComponentListener(new ComponentAdapter() {

			@Override
			public void componentResized(ComponentEvent e) {
				saveWindowSettings();

			}

			@Override
			public void componentMoved(ComponentEvent e) {
				saveWindowSettings();

			}

		});

		splitPane.addPropertyChangeListener(
				JSplitPane.DIVIDER_LOCATION_PROPERTY,
				new PropertyChangeListener() {

					@Override
					public void propertyChange(PropertyChangeEvent evt) {
						saveWindowSettings();

					}
				});

	}

	private void initializeServersTable() {
		serverList = new JTable();
		serverList.getSelectionModel().addListSelectionListener(
				new ListSelectionListener() {

					@Override
					public void valueChanged(ListSelectionEvent e) {
						int firstIndex = serverList.getSelectedRow();
						if (firstIndex > -1) {
							connectToServerAction.setEnabled(true);
						}

						ETServer etServer = getSelectedEtServer();

						if (lastSelectedServer != null) {
							lastSelectedServer.removePropertyChangeListener(
									"serverStatus", MainWindow.this);
						}
						if (etServer != null) {
							etServer.addPropertyChangeListener("serverStatus",
									MainWindow.this);
							lastSelectedServer = etServer;
							if (etServer.getServerStatus() != null) {
								playerModel.setPlayers(etServer
										.getServerStatus().getPlayers());
							}
						}

					}
				});

		serverList.setShowGrid(false);
		serverList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		serverList.getActionMap().put("copy", copyAction);
		serverList.getActionMap().put("paste", pasteServerAction);

		TableRowSorter<ServerListModel> rowSorter = new TableRowSorter<ServerListModel>(
				listModel);
		serverList.setDefaultRenderer(Object.class,
				new ServerListCellRenderer());
		serverList.setRowSorter(rowSorter);
		getServerList().setModel(getListModel());
		final JPopupMenu popupMenu = new JPopupMenu();
		popupMenu.add(connectToServerAction);
		popupMenu.add(changePasswordAction);
		popupMenu.add(copyAction);
		popupMenu.add(pasteServerAction);
		popupMenu.add(deleteServerAction);
		getServerList().getSelectionModel().addListSelectionListener(
				new ListSelectionListener() {

					@Override
					public void valueChanged(ListSelectionEvent e) {

						ETServer etServer = getSelectedEtServer();
						if (etServer == null) {
							return;
						}
						if (etServer.getPassword() != null
								|| etServer.getServerStatus() != null
								&& etServer.getServerStatus()
										.isPasswordProtected()) {
							changePasswordAction.setEnabled(true);
						} else {
							changePasswordAction.setEnabled(false);
						}

					}
				});

		serverList.setRowSelectionAllowed(true);
		serverList.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseReleased(MouseEvent e) {
				if (e.isPopupTrigger()) {
					popupMenu.show(serverList, e.getX(), e.getY());
					int rowAtPoint = serverList.rowAtPoint(e.getPoint());
					serverList.setRowSelectionInterval(rowAtPoint, rowAtPoint);
				}
			}
		});
		serverList.addKeyListener(new KeyListener() {

			@Override
			public void keyTyped(KeyEvent e) {

			}

			@Override
			public void keyReleased(KeyEvent e) {
				KeyStroke value = (KeyStroke) copyAction
						.getValue(AbstractAction.ACCELERATOR_KEY);
				char keyChar = e.getKeyChar();
				int modifiers = e.getModifiers();
				if (keyChar == value.getKeyChar()
						&& value.getModifiers() == modifiers) {
					copyAction.actionPerformed(null);
				}

			}

			@Override
			public void keyPressed(KeyEvent e) {
				// TODO Auto-generated method stub

			}
		});
	}

	JDialog createMessageDialog(String message) {
		final JDialog dialog = new JDialog();
		dialog.setLocationRelativeTo(getFrame());
		dialog.setLocationByPlatform(true);
		dialog.setModal(true);
		dialog.setLayout(new BorderLayout());
		JLabel label = new JLabel(message);
		dialog.add(label);
		dialog.pack();
		dialog.setAlwaysOnTop(true);

		return dialog;
	}

	public void setListModel(ServerListModel listModel) {
		this.listModel = listModel;
	}

	public ServerListModel getListModel() {
		return listModel;
	}

	public JTable getServerList() {
		return serverList;
	}

	public void setFrame(JFrame frame) {
		this.frame = frame;
	}

	public JFrame getFrame() {
		return frame;
	}

	@Override
	public void propertyChange(PropertyChangeEvent evt) {
		if (evt.getSource() == lastSelectedServer) {
			if (evt.getPropertyName().equals("serverStatus")) {
				final ServerStatus serverStatus = (ServerStatus) evt
						.getNewValue();
				SwingUtilities.invokeLater(new Runnable() {
					@Override
					public void run() {
						int selectedRow = playersTable.getSelectedRow();
						playerModel.setPlayers(serverStatus.getPlayers());

						if (selectedRow < 0) {
							return;
						}
						int rowCount = playersTable.getRowCount();
						if (rowCount > 0 && rowCount - 1 < selectedRow) {
							playersTable.setRowSelectionInterval(rowCount - 1,
									rowCount - 1);
						} else {
							playersTable.setRowSelectionInterval(selectedRow,
									selectedRow);
						}
					}
				});
			}
		}

	}

	public ETServer getSelectedEtServer() {
		int index = getServerList().getSelectedRow();
		if (index == -1) {
			return null;
		}
		int convertRowIndexToModel = getServerList().getRowSorter()
				.convertRowIndexToModel(index);
		final ETServer etServer = getListModel().getServers().get(
				convertRowIndexToModel);
		return etServer;
	}

	public ConnectToServerAction getConnectToServerAction() {
		return connectToServerAction;
	}

	public AddServerAction getAddServerAction() {
		return addServerAction;
	}

	public ChangePasswordAction getChangePasswordAction() {
		return changePasswordAction;
	}

	public DeleteServerAction getDeleteServerAction() {
		return deleteServerAction;
	}

	public DisplaySettingAction getSettingsAction() {
		return settingsAction;
	}

	public String getClipboardContetnts() {
		Clipboard systemClipboard = Toolkit.getDefaultToolkit()
				.getSystemClipboard();

		Transferable contents = systemClipboard.getContents(null);
		boolean hasTransferableText = (contents != null)
				&& contents.isDataFlavorSupported(DataFlavor.stringFlavor);
		if (hasTransferableText) {
			try {
				return (String) contents
						.getTransferData(DataFlavor.stringFlavor);
			} catch (UnsupportedFlavorException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}
		return null;

	}

	public void setClipboardContents(String value) {
		Clipboard systemClipboard = Toolkit.getDefaultToolkit()
				.getSystemClipboard();
		StringSelection selection = new StringSelection(value);
		systemClipboard.setContents(selection, null);
	}

	public ETServer showInsertServerIpDialog() {
		String result = JOptionPane.showInputDialog(getFrame(),
				"Insert server ip!");
		if (result == null) {
			return null;
		}
		if (result.isEmpty()) {
			return null;
		}

		ETServer etServer = ETServer.parseServerFromString(result);
		if (etServer == null) {
			return null;
		}
		etServer.setServerName(etServer.getIp() + ":" + etServer.getPort());
		return etServer;
	}

	public void saveWindowSettings() {

		Rectangle bounds = frame.getBounds();
		String settings = bounds.x + "," + bounds.y + "," + bounds.width + ","
				+ bounds.height + "," + splitPane.getDividerLocation();
		application.getApplicationSetting().setMainWindowSettings(settings);
		application.getApplicationSetting().save();

	}

	public void loadWindowSettings() {
		try {
			String mainWindowSettings = application.getApplicationSetting()
					.getMainWindowSettings();

			String[] split = mainWindowSettings.split(",");
			if (split.length == 5) {

				getFrame().setBounds(Integer.parseInt(split[0]),
						Integer.parseInt(split[1]), Integer.parseInt(split[2]),
						Integer.parseInt(split[3]));
				splitPane.setDividerLocation(Integer.parseInt(split[4]));
			}
		} catch (Exception e) {
			getFrame().pack();
		}

	}
}
